package edu.hawaii.ics414.blackjack.player;

import edu.hawaii.ics414.blackjack.card.Card;
import edu.hawaii.ics414.blackjack.card.GameDeck;

/**
 * A more experienced AI that accounts for the card(s) that the dealer has.
 * 
 * @author Branden Ogata
 *
 */

public class ExperiencedPlayer extends AIPlayer
{ 
  /**
   * Creates a new ExperiencedPlayer.
   * 
   * @param money The int equal to the starting amount of money for the new ExperiencedPlayer.
   * 
   */
  
  public ExperiencedPlayer(int money)
  {
    super(money);
  }
  
  /**
   * Returns the move of this ExperiencedPlayer.
   * 
   * @param deck The GameDeck containing the cards to use.
   * @param hand The int indicating the hand to play on.
   * @param hole The Card that the dealer has showing.
   * 
   * @return action The Action that this ExperiencedPlayer intends to play.
   * 
   */
  
  @Override
  public Action getMove(GameDeck deck, int hand, Card hole)
  {
    Action action = Action.STAND;
    
    // If a split is valid, then do so
    if (this.canSplit(hand))
    {
      action = Action.SPLIT;
    }
    
    // Else decide based on the dealer hole card as well as own cards
    else
    {
      // Soft
      if (this.isHandSoft(hand))
      {
        // Stand
        if (((this.sum(hand) >= 19) || 
            ((this.sum(hand) >= 18) && ((2 <= hole.getValue()) && (hole.getValue() <= 8)))))
        {
          action = Action.STAND;
        }
        
        // Hit
        if ((this.canHit(hand)) && 
            ((this.sum(hand) <= 18) && (hole.getValue() >= 9)) || 
            ((this.sum(hand) <= 17)))
        {
          action = Action.HIT;
        }
        
        // Double Down
        if ((this.canDoubleDown(hand)) && 
            (((13 <= this.sum(hand)) && (this.sum(hand) <= 18)) && 
             ((hole.getValue() == 5) || (hole.getValue() == 6))) || 
            (((15 <= this.sum(hand)) && (this.sum(hand) <= 18)) && (hole.getValue() == 4)) || 
            (((this.sum(hand) == 17) || (this.sum(hand) == 18)) && (hole.getValue() == 3))) 
        {
          action = Action.DOUBLE_DOWN;
        }
      }
      // Hard
      else
      {
        // Stand
        if ((((this.sum(hand) >= 17) && (hole.getValue() >= 7)) || 
             ((this.sum(hand) >= 12) && ((4 <= hole.getValue()) && (hole.getValue() <= 6))) ||
             ((this.sum(hand) >= 13) && ((hole.getValue() == 2)) || (hole.getValue() == 3))))
        {
          action = Action.STAND;
        }
        
        // Hit
        if ((this.canHit(hand)) && 
            ((this.sum(hand) <= 16) && (hole.getValue() >= 7)) || 
            ((this.sum(hand) <= 12) && ((hole.getValue() == 2) || (hole.getValue() == 3))) || 
            ((this.sum(hand) <= 8) && ((4 <= hole.getValue()) && (hole.getValue() <= 6))))
        {
          action = Action.HIT;
        }
        
        // Double Down
        if ((this.canDoubleDown(hand)) && 
            ((this.sum(hand) == 11) && (hole.getValue() <= 10)) ||
            ((this.sum(hand) == 10) && (hole.getValue() <= 9)) || 
            ((this.sum(hand) == 9) && ((3 <= hole.getValue()) && (hole.getValue() <= 6))))
        {
          action = Action.DOUBLE_DOWN;
        }
      }
    }
    
    return action;    
  }

  /**
   * Starts a new hand with an initial bet based on the last round.
   * 
   * @param deck The GameDeck to take cards from.
   * 
   */
  
  @Override
  public void startHand(GameDeck deck)
  {
    // If won the last round and can bet more, increase bet by 5
    if ((this.lastRound > 0) && (this.lastBet[0] + 5 <= 100))
    {
      this.setBet(0, this.lastBet[0] + 5);
    }
    // Else if lost the last round and can bet less, decrease bet by 5
    else if ((this.lastRound < 0) && (this.lastBet[0] - 5 > 0))
    {
      this.setBet(0, this.lastBet[0] - 5);
    }
    // Else do not change the bet
    else
    {
      this.setBet(0, this.lastBet[0]);
    }
    
    super.startHand(deck);
  }  
  
  /**
   * Returns a String representation of the cards for this ExperiencedPlayer.
   * This should show the cards face down.
   * 
   * @return desc A String representing the cards that this SemiProPlayer has.
   * 
   */  
  
  @Override
  public String getCards()
  {
    String desc = "";
    int i = 0;
    // For each hand
    for (Card[] hand : this.hands)
    {
      //prints the value and bet for the hand as well.
      if (hand[0] != null)
      {
        desc += "(Bet: ";
        desc += this.getBet(i);
        desc += ") ";
        desc += "Hand ";
        desc += (i + 1);
        desc += ": (Value: ";
        desc += handValue(i);
        desc += ")  -  ";
      }
      // Add each card to the String
      for (Card card : hand)
      {
        if (card != null)
        {
          desc += card + " ";
        }
      }
      
      if (hand[0] != null)
      {
        desc += "\n";
      }
      i++;
    }
    
    return desc;
  }

}
